<template>
  <div class="uploader clear"
       :class="{'uploader-full':hideDom}">
    <div class="uploader_wrap">
      <template v-if="!hideDom">
        <draggable class="uploader_files"
                    v-model="thumbs"
                    element="ul"
                    :options="dragOptions"
                    @end="drag">
          <li class="uploader_file"
              :class="'previewer-img'+mark"
              v-for="(item,index) in thumbs"
              :key="index"
              @click="preview(index)">
            <div class="img"
                  :style="`background-image:url(${item})`"></div>
            <div class="svg_wrap"
                 v-if="!disabled"
                 @click.stop="delImg(index)">
              <svg-icon name="close_m" color="rgba(33, 40, 44, 0.3)"/>
            </div>
          </li>
        </draggable>
      </template>
    </div>
    <div class="uploader_field"
             v-show="!(max && thumbs.length === max)">
      <input ref="fileIpt"
              class="uploader_input"
              type="file"
              :accept="mimeType"
              :multiple="isMul"
              @change="addImg">
    </div>

  </div>
</template>
<script>
import { ImagePreview } from 'vant'
import draggable from 'vuedraggable'
import { deepCopy } from '@/assets/js/utils.js'
import axios from 'axios'
import EXIF from 'exif-js'

export default {
  name: 'uploader',
  components: {
    [ImagePreview.name]: ImagePreview,
    draggable
  },
  props: {
    mark: {
      type: String,
      default: ''
    },
    value: Array,
    isMul: Boolean, // 多选
    url: String, // 服务器上传地址
    max: Number, // 限制最大数量
    type: { // 文件格式
      type: String,
      default: 'image'
    },
    draggable: {
      type: Boolean,
      default: true
    },
    hideDom: {
      type: Boolean, default: false
    },
    disabled: Boolean
  },
  data () {
    return {
      isDragging: false,
      thumbs: [], // 缩略图
      isShow: null // 是否打开预览图
    }
  },
  computed: {
    mimeType () {
      if (!this.type || this.type === 'image') return 'image/*'
      let types = this.type.split(',')
      let mimeType = []
      types.forEach(item => {
        mimeType.push('image/' + item)
      })
      return mimeType.join(',')
    },
    dragOptions () {
      return {
        disabled: !this.draggable,
        animation: 0,
        group: 'img',
        ghostClass: 'ghost',
        userId: ''
      }
    },
    imgList () {
      let list = []
      this.thumbs.forEach((item, index) => {
        list.push({
          url: item,
          index
        })
      })
      return list
    }
  },
  watch: {
    value: {
      handler (val, oVal) {
        this.thumbs = val
      },
      immediate: true
    },
    thumbs (val) {
      this.$emit('input', val)
    }
  },
  created () {
    // this.thumbs = [...this.value]
  },
  methods: {
    // 预览图片
    preview (ind) {
      // 预览图片
      ImagePreview({
        images: this.thumbs,
        startPosition: ind
      })
    },
    // 初始化变量
    async addImg () {
      const list = deepCopy(this.$refs.fileIpt.files)
      let len = list.length + this.thumbs.length
      if (this.isMul && this.max && (len > this.max)) {
        this.$toast('最多可选' + this.max + '张，选择的图片大于最大可选图片数量！')
        this.$refs.fileIpt.value = ''
        return
      }
      if (list.length === 0) {
        return
      }
      let sucNum = 0
      let errNum = 0
      for (let i = 0; i < list.length; i++) {
        let size = Math.floor(list[i].size / 1024 / 1024)
        if (list[i].size === 0) {
          this.$toast.clear()
          this.$toast(`第${i + 1}张图片内容为空，<br>请检查上传的图片~`)
          continue
        }
        if (size > 10) {
          this.$toast('图片过大，请上传10M以内的图片！')
          continue
        }
        if (list.length > 1) {
          this.$toast.loading({
            duration: 0,
            forbidClick: true,
            message: `正在上传${i + 1}/${list.length}`
          })
        } else {
          this.$toast.loading({
            duration: 0,
            forbidClick: true,
            message: `正在上传`
          })
        }
        try {
          let c = await this.checkOrientation(list[i])
          let p = await this.upload(c)
          this.thumbs.push(p)
          sucNum++
          if (i === list.length - 1) {
            this.$toast.clear()
          }
        } catch (e) {
          errNum++
        }
      }
      if (list.length > 1) {
        this.$toast(`上传完成，上传成功:${sucNum}张，上传失败：${errNum}张`)
      } else {
        if (!errNum) {
          this.$toast(`上传成功！`)
        }
      }
      this.$refs.fileIpt.value = ''
    },
    // 删除图片
    delImg (ind) {
      this.thumbs.splice(ind, 1)
    },
    drag (e) {
      // 拖动了图片顺序
      if (e.newIndex !== e.oldIndex) {
        // this.thumbs.move(e.newIndex, e.oldIndex)
        // this.previews.move(e.newIndex, e.oldIndex)
        // this.complete()
      }
    },
    upload (file) {
      // 上传图片
      let url = this.url

      if (!file) {
        return false
      }
      let formData = new FormData()
      formData.append('file', file)
      return new Promise((resolve, reject) => {
        axios.post(url, formData).then((res) => {
          resolve(res.data)
        }).catch(e => {
          reject(e)
        })
      })
    },

    checkOrientation (file) {
      return new Promise((resolve, reject) => {
        const reader = new FileReader()
        let orientation = null
        reader.onload = (e) => {
          let img = new Image()
          let canvas = document.createElement('canvas')
          let ctx = canvas.getContext('2d')

          img.src = e.target.result
          img.onload = () => {
            EXIF.getData(img, () => {
              orientation = EXIF.getTag(img, 'Orientation')
            })
            let w = img.width
            let h = img.height
            let r = img.width > img.height ? 1500 / img.width : 2000 / img.height
            if (r < 1) {
              w = w * r
              h = h * r
            }
            // 如果没有Orientation 则为Android
            if (!orientation) {
              canvas.width = w
              canvas.height = h
              ctx.drawImage(img, 0, 0, w, h)
            } else {
              // 如果有Orientation 则为IOS
              switch (orientation) {
                case 1:
                  canvas.width = w
                  canvas.height = h
                  ctx.drawImage(img, 0, 0, w, h)
                  break
                case 3:
                  canvas.width = w
                  canvas.height = h
                  ctx.rotate(Math.PI)
                  ctx.drawImage(img, -w, -h, w, h)
                  break
                case 6:
                  canvas.width = h
                  canvas.height = w
                  ctx.rotate(Math.PI / 2)
                  ctx.drawImage(img, 0, -h, w, h)
                  break
                case 8:
                  canvas.width = h
                  canvas.height = w
                  ctx.rotate(3 * Math.PI / 2)
                  ctx.drawImage(img, -w, 0, w, h)
                  break
              }
            }
            let dataURL = canvas.toDataURL('image/jpeg')

            resolve(dataURL)
            // iphone7转文件后，图片数据错误，无法保存
            // resolve(this.dataURLtoFile(dataURL, file.name))
          }
          // this.$set(item, 'src', e.target.result)
        }
        reader.readAsDataURL(file)
      })
    }
  }
}
</script>

<style lang="stylus" scoped>
positionTL($top = 0, $left = 0, $tl = 0, $tt = 0)
  translateEl($tl, $tt)
  position absolute
  top $top
  left $left
positionTR($top = 0, $right = 0, $tl = 0, $tt = 0)
  translateEl($tl, $tt)
  position absolute
  top $top
  right $right
positionFull($t = 0, $r = 0, $b = 0, $l = 0)
  position absolute
  top $t
  right $r
  bottom $b
  left $l
  -webkit-overflow-scrolling touch
// 盒子内容对齐
flexAlign($h = flex-start, $v = center)
  display flex
  justify-content $h
  align-items $v
.uploader-full
  position absolute
  top 0
  left 0
  right 0
  bottom 0
  opacity 0
  z-index 2
  .uploader_field
    position absolute
    top 0
    left 0
    width 100%
    height 100%
.uploader
  // flexAlign()
  flex-wrap wrap
  .ghost
    opacity 0.5
    background rgba(0, 0, 0, 0.1)
  .uploader_files
    // flexAlign()
    flex-wrap wrap
    .svg_wrap
      positionTR(0,0)
  .uploader_file,
  .uploader_field
    float left
    position relative
    margin-right 10px
    margin-bottom 10px
    width 77px
    height 77px
    border-radius 3px
    background-color rgba(250, 250, 250, 1)
    border 1px solid rgba(230, 230, 230, 1)
  .uploader_field
    border 1px dashed rgba(230, 230, 230, 1)
    &::before,
    &::after
      positionTL(50%,50%,-50%,-50%)
      content ''
      border-radius 1.5px
      background-color rgba(220, 220, 220, 1)
    &::before
      width 40%
      height 3px
    &::after
      height 40%
      width 3px
    &:active::before,
    &:active::after
      background-color rgba(200, 200, 200, 1)
    .uploader_input
      positionFull()
      opacity 0
      z-index 1
      -webkit-tap-highlight-color rgba(0, 0, 0, 0)
</style>
